# -*- coding: utf-8 -*-
# בש״ד
#
# Miraflores Blog for Django - Part of the Cuba Libre Project
# Copyright (C) 2009, Joshua "jag" Ginsberg <jag@flowtheory.net>
# 
# Por mi amor, que inspira a mi cada respiración y que echa de Cuba
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import pprint
import feedparser
from django.contrib.auth import models as auth
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.test import Client, TestCase
from django.conf import settings
settings.DEBUG = True
settings.HAYSTACK_XAPIAN_PATH='/tmp'
from miraflores.models import BlogEntry
from miraflores import feeds

class TestBlogEntryPermissions(TestCase):
    fixtures = ['miraflores_test']
    
    def setUp(self):
        self.anonymous = auth.AnonymousUser()
        self.girlfriend = auth.User.objects.get(username='hawtgrrl')
        self.joeschmoe = auth.User.objects.get(username='joeschmoe')
        self.mom = auth.User.objects.get(username='mom')
        self.dad = auth.User.objects.get(username='dad')
        self.blogger = auth.User.objects.get(username='blogger')
        self.family = auth.Group.objects.get(name='family')
        self.public_entry = BlogEntry.objects.get(slug='public-entry')
        self.unpublished_entry = BlogEntry.objects.get(slug='unpublished-entry')
        self.for_girlfriend = BlogEntry.objects.get(slug='to-my-girlfriend')
        self.for_family = BlogEntry.objects.get(slug='to-my-family')
        self.for_gf_and_family = BlogEntry.objects.get(slug='i-hate-my-boss')

    def test_public_entry(self):
        self.assertTrue(self.public_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.anonymous))
        self.assertTrue(self.public_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.blogger))
        self.assertTrue(self.public_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.girlfriend))
        
        self.assertTrue(self.public_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.joeschmoe))
        self.assertTrue(self.public_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.mom))
        self.assertTrue(self.public_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.dad))
    
    def test_unpublished_entry(self):
        self.assertFalse(self.unpublished_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.anonymous))
        self.assertTrue(self.unpublished_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.blogger))
        self.assertFalse(self.unpublished_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.girlfriend))
        
        self.assertFalse(self.unpublished_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.joeschmoe))
        self.assertFalse(self.unpublished_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.mom))
        self.assertFalse(self.unpublished_entry in \
                        BlogEntry.objects.can_be_seen_by_user(self.dad))

    def test_user_limited_entry(self):
        self.assertFalse(self.for_girlfriend in \
                        BlogEntry.objects.can_be_seen_by_user(self.anonymous))
        self.assertTrue(self.for_girlfriend in \
                        BlogEntry.objects.can_be_seen_by_user(self.blogger))
        self.assertTrue(self.for_girlfriend in \
                        BlogEntry.objects.can_be_seen_by_user(self.girlfriend))
        
        self.assertFalse(self.for_girlfriend in \
                        BlogEntry.objects.can_be_seen_by_user(self.joeschmoe))
        self.assertFalse(self.for_girlfriend in \
                        BlogEntry.objects.can_be_seen_by_user(self.mom))
        self.assertFalse(self.for_girlfriend in \
                        BlogEntry.objects.can_be_seen_by_user(self.dad))

    def test_group_limited_entry(self):
        self.assertFalse(self.for_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.anonymous))
        self.assertTrue(self.for_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.blogger))
        self.assertFalse(self.for_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.girlfriend))
        
        self.assertFalse(self.for_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.joeschmoe))
        self.assertTrue(self.for_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.mom))
        self.assertTrue(self.for_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.dad))

    def test_user_and_group_limited_entry(self):
        self.assertFalse(self.for_gf_and_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.anonymous))
        self.assertTrue(self.for_gf_and_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.blogger))
        self.assertTrue(self.for_gf_and_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.girlfriend))
        
        self.assertFalse(self.for_gf_and_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.joeschmoe))
        self.assertTrue(self.for_gf_and_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.mom))
        self.assertTrue(self.for_gf_and_family in \
                        BlogEntry.objects.can_be_seen_by_user(self.dad))

class TestFeedGeneration(TestCase):
    
    fixtures = ['miraflores_test']

    def setUp(self):
        self.anonymous = auth.AnonymousUser()
        self.girlfriend = auth.User.objects.get(username='hawtgrrl')
        self.joeschmoe = auth.User.objects.get(username='joeschmoe')
        self.mom = auth.User.objects.get(username='mom')
        self.dad = auth.User.objects.get(username='dad')
        self.blogger = auth.User.objects.get(username='blogger')
        self.family = auth.Group.objects.get(name='family')
        self.public_entry = BlogEntry.objects.get(slug='public-entry')
        self.unpublished_entry = BlogEntry.objects.get(slug='unpublished-entry')
        self.for_girlfriend = BlogEntry.objects.get(slug='to-my-girlfriend')
        self.for_family = BlogEntry.objects.get(slug='to-my-family')
        self.for_gf_and_family = BlogEntry.objects.get(slug='i-hate-my-boss')
    
    def test_all_public_entries(self):
        c = Client()
        response = c.get(
            reverse('miraflores_syndication',
                    args=['rss']))
        self.assertEqual(response.status_code, 200)
        d = feedparser.parse(response.content)
        self.assertEqual(d.feed.title, Site.objects.get_current().name)
        self.assertTrue(
            d.feed.link.endswith(reverse('miraflores_blog_entry_list')))
        self.assertEqual(len(d.entries), 1)
    
    def test_all_entries_with_login(self):
        c = Client()
        auth_token = feeds.generate_user_token(self.girlfriend)
        response = c.get(
            reverse('miraflores_syndication',
                    args=['rss/%s' % auth_token]))
        self.assertEqual(response.status_code, 200)
        d = feedparser.parse(response.content)
        self.assertEqual(d.feed.title, Site.objects.get_current().name)
        self.assertTrue(
            d.feed.link.endswith(reverse('miraflores_blog_entry_list')))
        self.assertEqual(len(d.entries), 3)

    def test_tagged_entries(self):
        c = Client()
        response = c.get(
            reverse('miraflores_syndication',
                    args=['rss/tag/stuff/']))
        self.assertEqual(response.status_code, 200)
        d = feedparser.parse(response.content)
        self.assertTrue(d.feed.title.startswith(Site.objects.get_current().name))
        self.assertTrue('stuff' in d.feed.title)
        self.assertTrue(
            d.feed.link.endswith(reverse('miraflores_tagged_entry_list',
                                         args=['stuff'])))
        self.assertEqual(len(d.entries), 1)
        self.assertTrue(d.entries[0].link.endswith(
            self.public_entry.get_absolute_url()))
        
    def test_tagged_entries_with_login(self):
        c = Client()
        auth_token = feeds.generate_user_token(self.girlfriend)
        response = c.get(
            reverse('miraflores_syndication',
                    args=['rss/tag/love/%s' % auth_token]))
        self.assertEqual(response.status_code, 200)
        d = feedparser.parse(response.content)
        self.assertTrue(d.feed.title.startswith(Site.objects.get_current().name))
        self.assertTrue('love' in d.feed.title)
        self.assertTrue(
            d.feed.link.endswith(reverse('miraflores_tagged_entry_list',
                                         args=['love'])))
        self.assertEqual(len(d.entries), 1)
        self.assertTrue(d.entries[0].link.endswith(
            self.for_girlfriend.get_absolute_url()))

    def test_search_entries(self):
        c = Client()
        response = c.get(
            reverse('miraflores_syndication',
                    args=['rss/search/public/']))
        self.assertEqual(response.status_code, 200)
        d = feedparser.parse(response.content)
        self.assertTrue(d.feed.title.startswith(Site.objects.get_current().name))
        self.assertTrue('public' in d.feed.title)
        self.assertTrue(
            reverse('miraflores_search') in d.feed.link)
        self.assertEqual(len(d.entries), 1)
        self.assertTrue(d.entries[0].link.endswith(
            self.public_entry.get_absolute_url()))

    def test_search_entries_with_login(self):
        c = Client()
        auth_token = feeds.generate_user_token(self.girlfriend)
        response = c.get(
            reverse('miraflores_syndication',
                    args=['rss/search/boss/%s' % auth_token]))
        self.assertEqual(response.status_code, 200)
        d = feedparser.parse(response.content)
        self.assertTrue(d.feed.title.startswith(Site.objects.get_current().name))
        self.assertTrue('boss' in d.feed.title)
        self.assertTrue(
            reverse('miraflores_search') in d.feed.link)
        self.assertEqual(len(d.entries), 1)
        self.assertTrue(d.entries[0].link.endswith(
            self.for_gf_and_family.get_absolute_url()))
